package com.wpml.netty.rpc.server;

import com.wpml.netty.rpc.Dispatcher;
import com.wpml.netty.rpc.common.MyBody;
import com.wpml.netty.rpc.util.SerDerUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;

import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;

/**
 * @Description http协议消息处理器
 * @Date 2021-05-10
 * @Author wangpei
 **/
public class HttpRequestHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress();
        System.out.println("httpClient " + address.getPort() + " 连接关闭");
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 获取请求数据
        FullHttpRequest request = (FullHttpRequest) msg;
        ByteBuf reqBuf = request.content();

        byte[] data = new byte[reqBuf.readableBytes()];
        reqBuf.readBytes(data);
        ObjectInputStream oin = new ObjectInputStream(new ByteArrayInputStream(data));
        MyBody reqBody = (MyBody) oin.readObject();
        // 调用接口方法
        String serviceName = reqBody.getName();
        String methodName = reqBody.getMethodName();

        Object obj = Dispatcher.invokeMap.get(serviceName);
        Class<?> clazz = obj.getClass();
        Object res = null;
        try {
            Method method = clazz.getMethod(methodName, reqBody.getParameterTypes());
            res = method.invoke(obj, reqBody.getArgs());
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }

        // 封装返回值
        MyBody respBody = MyBody.builder()
                .res(res)
                .build();
        byte[] bodyByte = SerDerUtil.ser(respBody);

        DefaultFullHttpResponse response = new DefaultFullHttpResponse(
                HttpVersion.HTTP_1_1,
                HttpResponseStatus.OK,
                Unpooled.copiedBuffer(bodyByte));

        ctx.writeAndFlush(response);
    }

}
